home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / Dylan Related / Marlais / marlais.el (for emacs)
Encoding:
Text File  |  1995-03-15  |  11.9 KB  |  324 lines  |  [TEXT/ttxt]

  1. ;;; marlais.el --- Dylan process in a buffer.  Adapted from cmuscheme.el
  2.  
  3. ;; Author: Joseph N. Wilson <jnw@cis.ufl.edu>
  4. ;; Keywords: processes, dylan
  5.  
  6. ;; This file is lifted almost verbatim from cmuscheme.el, which is
  7. ;; a part of GNU Emacs written by Olin Shivers <olin.shivers@cs.cmu.edu>
  8.  
  9. ;; cmuscheme.el is (and thus marlais.el is)
  10. ;; Copyright (C) 1988 Free Software Foundation, Inc.
  11. ;; marlais.el is Copyright (C) 1994 J.N. Wilson under the same terms and
  12. ;; conditions as cmuscheme.el.
  13.  
  14. ;; GNU Emacs is free software; you can redistribute it and/or modify
  15. ;; it under the terms of the GNU General Public License as published by
  16. ;; the Free Software Foundation; either version 2, or (at your option)
  17. ;; any later version.
  18.  
  19. ;; GNU Emacs is distributed in the hope that it will be useful,
  20. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. ;; GNU General Public License for more details.
  23.  
  24. ;; You should have received a copy of the GNU General Public License
  25. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  26. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  27.  
  28. ;;; Commentary:
  29.  
  30. ;;;    This is a customisation of comint-mode (see comint.el)
  31.  
  32. ;; YOUR .EMACS FILE
  33. ;;=============================================================================
  34. ;; Some suggestions for your .emacs file.
  35. ;;
  36. ;; ; If marlais.el lives in some non-standard directory, you must tell emacs
  37. ;; ; where to get it. This may or may not be necessary.
  38. ;; (setq load-path (cons (expand-file-name "~jones/lib/emacs") load-path))
  39. ;;
  40. ;; ; Autoload run-dylan from file marlais.el
  41. ;; (autoload 'run-dylan "marlais"
  42. ;;           "Run an inferior Dylan process."
  43. ;;           t)
  44. ;;
  45. ;; ; Files ending in ".dyl" are Dylan source, 
  46. ;; ; so put their buffers in dylan-mode.
  47. ;; (setq auto-mode-alist 
  48. ;;       (cons '("\\.dyl$" . dylan-mode)  
  49. ;;             auto-mode-alist))
  50. ;;
  51. ;; ; Define C-c t to run my favorite command in inferior dylan mode:
  52. ;; (setq marlais-load-hook
  53. ;;       '((lambda () (define-key inferior-dylan-mode-map "\C-ct"
  54. ;;                                'favorite-cmd))))
  55.  
  56. ;;;
  57. ;;; Code:
  58.  
  59. (require 'dylan-mode)
  60. (require 'comint)
  61.  
  62. ;;; INFERIOR DYLAN MODE STUFF
  63. ;;;============================================================================
  64.  
  65. (defvar inferior-dylan-mode-hook nil
  66.   "*Hook for customising inferior-dylan mode.")
  67. (defvar inferior-dylan-mode-map nil)
  68.  
  69. (cond ((not inferior-dylan-mode-map)
  70.        (setq inferior-dylan-mode-map
  71.          (full-copy-sparse-keymap comint-mode-map))
  72.        (define-key inferior-dylan-mode-map "\C-x\C-e" 'comint-send-input)
  73.        (define-key inferior-dylan-mode-map "\C-c\C-l" 'dylan-load-file)
  74.        (define-key inferior-dylan-mode-map "\M-\C-m" 'dylan-send-from-prompt)
  75.        (dylan-mode-commands inferior-dylan-mode-map))) 
  76.  
  77.  
  78. ;; Install the process communication commands in the dylan-mode keymap.
  79. (define-key dylan-mode-map "\C-c\C-r" 'dylan-send-region)
  80. (define-key dylan-mode-map "\C-c\M-r" 'dylan-send-region-and-go)
  81. (define-key dylan-mode-map "\C-c\C-z" 'switch-to-dylan)
  82. (define-key dylan-mode-map "\C-c\C-l" 'dylan-load-file)
  83.  
  84.  
  85. (defvar dylan-buffer)
  86.  
  87. (defun inferior-dylan-mode ()
  88.   "Major mode for interacting with an inferior Dylan process.
  89. The following commands are available:
  90. \\{inferior-dylan-mode-map}
  91.  
  92. A Dylan process can be fired up with M-x run-dylan.
  93.  
  94. Customisation: Entry to this mode runs the hooks on comint-mode-hook and
  95. inferior-dylan-mode-hook (in that order).
  96.  
  97. You can send text to the inferior Dylan process from other buffers containing
  98. Dylan source.  
  99.     switch-to-dylan switches the current buffer to the Dylan process buffer.
  100.     dylan-send-region sends the current region to the Dylan process.
  101.     dylan-send-region-and-go switches to the Dylan process buffer after
  102.       sending text.
  103. For information on running multiple processes in multiple buffers, see
  104. documentation for variable dylan-buffer.
  105.  
  106. Commands:
  107. Return after the end of the process' output sends the text from the 
  108.     end of process to point.
  109. Return before the end of the process' output copies the sexp ending at point
  110.     to the end of the process' output, and sends it.
  111. Delete converts tabs to spaces as it moves back.
  112. Tab indents for Dylan; with argument, shifts rest
  113.     of expression rigidly with the current line.
  114. C-M-q does Tab on each line starting within following expression.
  115. Paragraphs are separated only by blank lines.  Semicolons start comments.
  116. If you accidentally suspend your process, use \\[comint-continue-subjob]
  117. to continue it."
  118.   (interactive)
  119.   (comint-mode)
  120.   ;; Customise in inferior-dylan-mode-hook
  121.   (setq comint-prompt-regexp "^\? *") ; OK for Marlais
  122.   (dylan-mode-variables)
  123.   (setq major-mode 'inferior-dylan-mode)
  124.   (setq mode-name "Inferior Dylan")
  125.   (setq mode-line-process '(": %s"))
  126.   (use-local-map inferior-dylan-mode-map)
  127.   (setq comint-input-filter (function dylan-input-filter))
  128.   (setq comint-input-sentinel (function ignore))
  129.   (setq comint-get-old-input (function dylan-get-old-input))
  130.   (run-hooks 'inferior-dylan-mode-hook))
  131.  
  132.  
  133. (defvar inferior-dylan-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
  134.   "*Input matching this regexp are not saved on the history list.
  135. Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
  136.  
  137. (defun dylan-input-filter (str)
  138.   "Don't save anything matching inferior-dylan-filter-regexp"
  139.   (not (string-match inferior-dylan-filter-regexp str)))
  140.  
  141. (defun dylan-get-old-input ()
  142.   "Snarf the sexp ending at point"
  143.   (save-excursion
  144.     (let ((end (point)))
  145.       (backward-sexp)
  146.       (buffer-substring (point) end))))
  147.  
  148. (defun dylan-args-to-list (string)
  149.   (let ((where (string-match "[ \t]" string)))
  150.     (cond ((null where) (list string))
  151.       ((not (= where 0))
  152.        (cons (substring string 0 where)
  153.          (dylan-args-to-list (substring string (+ 1 where)
  154.                          (length string)))))
  155.       (t (let ((pos (string-match "[^ \t]" string)))
  156.            (if (null pos)
  157.            nil
  158.          (dylan-args-to-list (substring string pos
  159.                          (length string)))))))))
  160.  
  161. (defvar dylan-program-name "marlais"
  162.   "*Program invoked by the run-dylan command")
  163.  
  164. (defun run-dylan (cmd)
  165.   "Run an inferior Dylan process, input and output via buffer *dylan*.
  166. If there is a process already running in *dylan*, just switch to that buffer.
  167. With argument, allows you to edit the command line (default is value
  168. of dylan-program-name).  Runs the hooks from inferior-dylan-mode-hook
  169. \(after the comint-mode-hook is run).
  170. \(Type \\[describe-mode] in the process buffer for a list of commands.)"
  171.  
  172.   (interactive (list (if current-prefix-arg
  173.              (read-string "Run Dylan: " dylan-program-name)
  174.              dylan-program-name)))
  175.   (if (not (comint-check-proc "*dylan*"))
  176.       (let ((cmdlist (dylan-args-to-list cmd)))
  177.     (set-buffer (apply 'make-comint "dylan" (car cmdlist)
  178.                nil (cdr cmdlist)))
  179.     (inferior-dylan-mode)))
  180.   (setq dylan-buffer "*dylan*")
  181.   (switch-to-buffer "*dylan*"))
  182.  
  183. (defun dylan-get-old-input ()
  184.   "Snarf the text between prompt and point"
  185.   (save-excursion
  186.     (let ((end (point)))
  187.       (comint-prev-prompt)
  188.       (buffer-substring (point) end))))
  189.  
  190. (defun dylan-send-region-recursively (string)
  191.   (let ((index (string-match "[^\n]\n" string)))
  192.     (if index
  193.     (progn
  194.       (setq index (+ index 1))
  195.       ;; (message "%s" (substring string 1 index))
  196.       ;; (sleep-for 1)
  197.       (comint-send-string (dylan-proc) (substring string 0 index))
  198.       (comint-send-string (dylan-proc) " ")
  199.       (dylan-send-region-recursively (substring string index)))
  200.       (progn
  201.     ;; (message "%s" string)
  202.     (comint-send-string (dylan-proc) string)))))
  203.  
  204. (defun dylan-send-region (start end)
  205.   "Send the current region to the inferior Dylan process."
  206.   (interactive "r")
  207.   ;;  (comint-send-string (dylan-proc) (buffer-substring start end))
  208.   ;;  (comint-send-string (dylan-proc) "\n"))
  209.   (dylan-send-region-recursively (buffer-substring start end)))
  210.  
  211.  
  212. (defun dylan-send-from-prompt ()
  213.   "Send input starting at the last prompt to the inferior Dylan process."
  214.   (interactive)
  215.   (dylan-send-region (save-excursion (comint-prev-prompt 1) (point)) (point)))
  216.  
  217. (defun switch-to-dylan (eob-p)
  218.   "Switch to the dylan process buffer.
  219. With argument, positions cursor at end of buffer."
  220.   (interactive "P")
  221.   (if (get-buffer dylan-buffer)
  222.       (pop-to-buffer dylan-buffer)
  223.       (error "No current process buffer. See variable dylan-buffer."))
  224.   (cond (eob-p
  225.      (push-mark)
  226.      (goto-char (point-max)))))
  227.  
  228. (defun dylan-send-region-and-go (start end)
  229.   "Send the current region to the inferior Dylan process.
  230. Then switch to the process buffer."
  231.   (interactive "r")
  232.   (dylan-send-region start end)
  233.   (switch-to-dylan t))
  234.  
  235. (defvar dylan-source-modes '(dylan-mode)
  236.   "*Used to determine if a buffer contains Dylan source code.
  237. If it's loaded into a buffer that is in one of these major modes, it's
  238. considered a dylan source file by dylan-load-file.
  239. Used by these commands to determine defaults.")
  240.  
  241. (defvar dylan-prev-l/c-dir/file nil
  242.   "Caches the last (directory . file) pair.
  243. Caches the last pair used in the last dylan-load-file command.
  244. Used for determining the default in the next one.")
  245.  
  246. (defun dylan-load-file (file-name)
  247.   "Load a Dylan file into the inferior Dylan process."
  248.   (interactive (comint-get-source "Load Dylan file: " dylan-prev-l/c-dir/file
  249.                   dylan-source-modes t)) ; T because LOAD 
  250.                                                           ; needs an exact name
  251.   (comint-check-source file-name) ; Check to see if buffer needs saved.
  252.   (setq dylan-prev-l/c-dir/file (cons (file-name-directory    file-name)
  253.                        (file-name-nondirectory file-name)))
  254.   (comint-send-string (dylan-proc) (concat "load (\""
  255.                         file-name
  256.                         "\"\)\n")))
  257.  
  258.  
  259. (defvar dylan-buffer nil "*The current dylan process buffer.
  260.  
  261. MULTIPLE PROCESS SUPPORT
  262. ===========================================================================
  263. Dylan.el supports, in a fairly simple fashion, running multiple Dylan
  264. processes. To run multiple Dylan processes, you start the first up with
  265. \\[run-dylan]. It will be in a buffer named *dylan*. Rename this buffer
  266. with \\[rename-buffer]. You may now start up a new process with another
  267. \\[run-dylan]. It will be in a new buffer, named *dylan*. You can
  268. switch between the different process buffers with \\[switch-to-buffer].
  269.  
  270. Commands that send text from source buffers to Dylan processes --
  271. like dylan-send-region  -- have to choose a
  272. process to send to, when you have more than one Dylan process around. This
  273. is determined by the global variable dylan-buffer. Suppose you
  274. have three inferior Dylans running:
  275.     Buffer    Process
  276.     foo        dylan
  277.     bar        dylan<2>
  278.     *dylan*    dylan<3>
  279. If you do a \\[dylan-send-region-and-go] command on some Dylan source
  280. code, what process do you send it to?
  281.  
  282. - If you're in a process buffer (foo, bar, or *dylan*), 
  283.   you send it to that process.
  284. - If you're in some other buffer (e.g., a source file), you
  285.   send it to the process attached to buffer dylan-buffer.
  286. This process selection is performed by function dylan-proc.
  287.  
  288. Whenever \\[run-dylan] fires up a new process, it resets dylan-buffer
  289. to be the new process's buffer. If you only run one process, this will
  290. do the right thing. If you run multiple processes, you can change
  291. dylan-buffer to another process buffer with \\[set-variable].
  292.  
  293. More sophisticated approaches are, of course, possible. If you find yourself
  294. needing to switch back and forth between multiple processes frequently,
  295. you may wish to consider ilisp.el, a larger, more sophisticated package
  296. for running inferior Lisp and Dylan processes. The approach taken here is
  297. for a minimal, simple implementation. Feel free to extend it.")
  298.  
  299. (defun dylan-proc ()
  300.   "Returns the current dylan process. See variable dylan-buffer."
  301.   (let ((proc (get-buffer-process (if (eq major-mode 'inferior-dylan-mode)
  302.                       (current-buffer)
  303.                       dylan-buffer))))
  304.     (or proc
  305.     (error "No current process. See variable dylan-buffer"))))
  306.  
  307.  
  308. ;;; Do the user's customisation...
  309.  
  310. (defvar marlais-load-hook nil
  311.   "This hook is run when marlais is loaded in.
  312. This is a good place to put keybindings.")
  313.     
  314. (run-hooks 'marlais-load-hook)
  315.  
  316.  
  317. ;;; CHANGE LOG
  318.  
  319. (provide 'marlais)
  320.  
  321. ;;; marlais.el ends here
  322.  
  323.  
  324.